package mdt.figure;

import org.tigris.gef.base.Editor;
import org.tigris.gef.presentation.FigRect;
import mdt.action.DecFontAction;
import mdt.action.IncFontAction;
import mdt.action.SetFillColorAction;
import mdt.action.SetTextColorAction;

import javax.swing.*;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.Element;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by xiaobyu on 7/13/2016.
 */
public class FigEditToolbar extends FigRect{
    JToolBar toolbar1;
    JToolBar toolbar2;

    private JTextPane pane;
    private CaretListener caratListener;
    private transient Editor editor;
    private boolean disableActionListener = false;

    Map<String, Action> actionMap = new HashMap<>();

    public FigEditToolbar(int x, int y) {
        super(x, y, 0, 0);
        initToolBar();
        setFilled(false);
        setLineWidth(1);
        setLineColor(null);
        setVisible(false);
    }

    public void setVisible(boolean visible) {
        if (isVisible() == visible) {
            return;
        }

        if (editor != null) {
            JComponent drawingPanel = (JPanel) editor.getJComponent();
            Component awtComp = drawingPanel;
            while (!(awtComp instanceof RootPaneContainer) && awtComp != null) {
                awtComp = awtComp.getParent();
            }

            if (awtComp == null) {
                super.setVisible(visible);
                return;
            }

            JLayeredPane layeredPane = ((RootPaneContainer) awtComp).getLayeredPane();
            if (visible) {
                layeredPane.add(toolbar1, JLayeredPane.POPUP_LAYER, 0);
                layeredPane.add(toolbar2, JLayeredPane.POPUP_LAYER, 0);
                //toolbar1.setVisible(true);
                //toolbar2.setVisible(true);
            } else {
                //toolbar1.setVisible(false);
                //toolbar2.setVisible(false);
                layeredPane.remove(toolbar1);
                layeredPane.remove(toolbar2);
            }
        }
        super.setVisible(visible);
    }

    public void setTextPane(JTextPane newPane) {
        if (pane == newPane) return;

        if (pane != null) {
            pane.removeCaretListener(caratListener);
        }

        pane = newPane;

        if (pane != null) {
            initActionMap();
            pane.addCaretListener(caratListener);
        }
    }

    private void initActionMap() {
        actionMap.clear();
        Action[] actions = pane.getActions();
        for (Action action : actions) {
            actionMap.put((String) action.getValue(Action.NAME), action);
        }
    }

    private JButton createActionButton(final String actionKey, String resource) {
        JButton b = new JButton(new ImageIcon(FigEditToolbar.class.getResource("/resources/" + resource))) {

            @Override
            public float getAlignmentY() {
                return 0.5f;
            }
        };
        b.setRequestFocusEnabled(false);
        //b.setMargin(new Insets(1, 1, 1, 1));
        b.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Action action = actionMap.get(actionKey);
                if (action != null) {
                    action.actionPerformed(e);
                }
            }
        });

        return b;
    }

    private JButton createActionButton(Action action) {
        JButton b = new JButton(action) {

            @Override
            public float getAlignmentY() {
                return 0.5f;
            }
        };
        b.setHideActionText(true);
        b.setRequestFocusEnabled(false);
        return b;
    }

        private JComboBox fontBox;
    private JComboBox sizeBox;

    private void initToolBar() {
        toolbar1 = new JToolBar();
        toolbar1.add(createActionButton("font-bold", "bold-16.png"));
        toolbar1.add(createActionButton("font-italic", "italic-16.png"));
        toolbar1.add(createActionButton("left-justify", "align_left-16.png"));
        toolbar1.add(createActionButton("center-justify", "align_center-16.png"));
        toolbar1.add(createActionButton("right-justify", "align_right-16.png"));
        toolbar1.add(createActionButton(new SetTextColorAction()));
        toolbar1.add(createActionButton(new SetFillColorAction()));

        toolbar1.setFloatable(false);
        toolbar1.setBorderPainted(false);
        Dimension size = toolbar1.getPreferredSize();
        toolbar1.setSize(size.width, size.height);


        toolbar2 = new JToolBar();

        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        String[] fontsName = ge.getAvailableFontFamilyNames();
        fontBox = new JComboBox(fontsName);
        fontBox.setPrototypeDisplayValue("Dialog Box");
        fontBox.setRequestFocusEnabled(false);
        //fontBox.setPreferredSize(new Dimension(50, size.height));
        //fontBox.setSize(50, size.height);
        toolbar2.add(fontBox);

        String fontSizeArr[] = {"8", "9", "10", "11", "12", "14", "16", "18", "20", "24",
                "28", "32", "36", "40", "44", "48", "54", "60", "66", "72", "80", "88", "96"};
        sizeBox = new JComboBox(fontSizeArr);
        sizeBox.setPrototypeDisplayValue(18);
        sizeBox.setRequestFocusEnabled(false);
        sizeBox.setEditable(false);
        toolbar2.add(sizeBox);


        fontBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!disableActionListener)
                new StyledEditorKit.FontFamilyAction("set-font-family", (String)fontBox.getSelectedItem()).actionPerformed(e);
            }
        });

        sizeBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (!disableActionListener)
                new StyledEditorKit.FontSizeAction("set-font-size", Integer.parseInt((String) sizeBox.getSelectedItem())).actionPerformed(e);
            }
        });

        toolbar2.add(createActionButton(new IncFontAction()));
        toolbar2.add(createActionButton(new DecFontAction()));
        toolbar2.setSize(size.width, size.height); //same size as toolbar1
        toolbar2.setFloatable(false);
        toolbar2.setBorderPainted(false);

        caratListener = new CaretListener() {
            @Override
            public void caretUpdate(CaretEvent e) {
                Element element = pane.getStyledDocument().getCharacterElement(e.getDot());
                if (element != null) {
                    AttributeSet atts = element.getAttributes();
                    String family = StyleConstants.getFontFamily(atts);
                    int size = StyleConstants.getFontSize(atts);
                    disableActionListener = true;
                    fontBox.setSelectedItem(family);
                    sizeBox.setSelectedItem(String.valueOf(size));
                    disableActionListener = false;
                }
            }
        };

        setBounds(_x, _y, size.width + 4, size.height * 2 + 6);


    }

    protected void setBoundsImpl(int x, int y, int w, int h) {

        Dimension size = toolbar1.getSize();
        Rectangle bbox = new Rectangle(x + 2, y + 2, size.width, size.height);
        if (editor != null) {
            JComponent drawingPanel = (JPanel) editor.getJComponent();
            Component awtComp = drawingPanel;
            while (!(awtComp instanceof RootPaneContainer) && awtComp != null) {
                awtComp = awtComp.getParent();
            }
            JLayeredPane layeredPane = ((RootPaneContainer) awtComp).getLayeredPane();
            bbox = SwingUtilities.convertRectangle(drawingPanel, bbox, layeredPane);
        }
        toolbar2.setLocation(bbox.x, bbox.y);
        toolbar1.setLocation(bbox.x, bbox.y + size.height + 2);

        super.setBoundsImpl(x, y, size.width + 4, size.height * 2 + 6);
    }

    public Editor getEditor() {
        return editor;
    }

    public void setEditor(Editor editor) {
        this.editor = editor;
    }
}
